package com.ap.core.business.message.validation.handler;


import com.ap.core.business.exception.service.ExceptionDetailsService;
import com.ap.core.business.info.ValidationInfo;
import com.ap.core.business.message.domain.translators.BindingMetaData;
import com.ap.core.business.message.validation.listener.ValidationListener;
import com.ap.core.common.types.InputMessageType;
import com.ap.core.common.types.ValidationType;
import com.ap.core.dao.MessageBusinessRuleDetailsDao;
import com.ap.core.domain.ExceptionDetails;
import com.ap.core.domain.MessageBusinessRuleDetails;
import com.ap.core.domain.MessageBusinessRuleDetailsId;
import com.ap.core.exception.BusinessFailureException;
import com.ap.core.message.info.RequestMessageInfo;
import com.ap.core.validation.info.ValidationResult;
import com.ap.core.validation.message.info.MessageValidationInfo;
import com.ap.core.validation.message.info.OriginalInfo;
import com.ap.core.validation.service.BusinessValidationService;

/**
 * User: Ranjit.Singh
 * Abstract class for ValidationHandler for different messages
 */
public abstract class AbstractValidationHandler<REQ extends RequestMessageInfo<?>, OI extends OriginalInfo> implements ValidationHandler<REQ> {

    private BusinessValidationService<MessageValidationInfo<REQ, OI>> businessValidationService;
    
    private MessageBusinessRuleDetailsDao messageBusinessRuleDetailsDao;
    
    private ExceptionDetailsService exceptionDetailsService;

    /**
     * {@inheritDoc}
     */
    @Override
    public void validate(final REQ request, final BindingMetaData metaData, ValidationListener validationListener) throws BusinessFailureException {
        final MessageValidationInfo<REQ ,OI> messageValidationInfo =  getMessageValidationInfo(request, metaData);

        ValidationResult messageValidationResult = businessValidationService.validate(messageValidationInfo, getValidationType(metaData));
        if (messageValidationResult.isValid()) {
            validationListener.onValidMessage();
        } else {
            for(ValidationInfo validationInfo: messageValidationResult.getFailedRulesInfo()){
            	
            	final MessageBusinessRuleDetails messageRuleDetails = messageBusinessRuleDetailsDao.findById(new MessageBusinessRuleDetailsId(metaData.getInputMessageType().getInputMsgTypeEnum().name(), 
            			                                                                                                              validationInfo.getInternalBusinessErrorCode()));
            	
            	final ExceptionDetails exceptionDetails = new ExceptionDetails(metaData.getReconciliationInfo().getReconciliationCycleId(),
                                                                               metaData.getReconciliationInfo().getReconciliationDate(), 
                                                                               messageRuleDetails.getId().getMessageTypeCode(), 
                                                                               messageRuleDetails.getId().getInternalBusinessErrorCode(), 
                                                                               metaData.getApMessageId());
            
                exceptionDetailsService.persistExceptionDetails(exceptionDetails);
                
                validationInfo.setExternalBusinessErrorCode(messageRuleDetails.getExternalBusinessErrorCode());
            	validationInfo.setExternalBusinessErrorDescription(messageRuleDetails.getExternalBusinessErrorDescription());
            	validationInfo.setInternalBusinessErrorDescription(messageRuleDetails.getInternalBusinessErrorDescription());
            	validationInfo.setRuleDescription(messageRuleDetails.getRuleDescription());
            	validationInfo.setExceptionDetailsId(exceptionDetails.getId());
            }
            validationListener.onRejectedMessage(messageValidationResult.getFailedRulesInfo());
        }

    }

    protected ValidationType getValidationType(BindingMetaData metaData){
        return ValidationType.valueOf(metaData.getInputMessageType(), false);
    }

    abstract protected MessageValidationInfo<REQ ,OI> getMessageValidationInfo(REQ request, BindingMetaData metaData);


    public void setBusinessValidationService(BusinessValidationService<MessageValidationInfo<REQ, OI>> businessValidationService) {
        this.businessValidationService = businessValidationService;
    }
    
	/**
	 * @param messageBusinessRuleDetailsDao the messageBusinessRuleDetailsDao to set
	 */
	public void setMessageBusinessRuleDetailsDao(
			MessageBusinessRuleDetailsDao messageBusinessRuleDetailsDao) {
		this.messageBusinessRuleDetailsDao = messageBusinessRuleDetailsDao;
	}

	/**
	 * @param exceptionDetailsService the exceptionDetailsService to set
	 */
	public void setExceptionDetailsService(
			ExceptionDetailsService exceptionDetailsService) {
		this.exceptionDetailsService = exceptionDetailsService;
	}

   
}
